package com.example.learnspringboot09cache.config;


import com.example.learnspringboot09cache.bean.Department;
import com.example.learnspringboot09cache.bean.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.CacheKeyPrefix;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.format.support.DefaultFormattingConversionService;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.UnknownHostException;
import java.time.Duration;

@Configuration
public class MyRedisConfig {

    @Bean
    public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
        template.setDefaultSerializer(ser);
        return template;
    }
    @Bean
    public RedisTemplate<Object, Department> deptRedisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Department> ser = new Jackson2JsonRedisSerializer<Department>(Department.class);
        template.setDefaultSerializer(ser);
        return template;
    }

    /*
    https://blog.csdn.net/qq_43366662/article/details/121249962

    https://huaweicloud.csdn.net/637ef512df016f70ae4ca5cb.html
     */

    @Bean
    public RedisCacheManager defaultCacheManager(RedisConnectionFactory connectionFactory) throws InvocationTargetException, IllegalAccessException, InstantiationException {
        //对 对象类型（employee）和string类型的序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        Jackson2JsonRedisSerializer<String> keySerializer = new Jackson2JsonRedisSerializer<>(String.class);

        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
        RedisCacheConfiguration.registerDefaultConverters(conversionService);
        RedisCacheConfiguration redisCacheConfiguration = null;

        Constructor[] constructors = RedisCacheConfiguration.class.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            constructor.setAccessible(true);
            if(constructor.getParameterTypes().length==7){//因为只有构造方法，所以判断方式比较随意
                redisCacheConfiguration = (RedisCacheConfiguration) constructor.newInstance(Duration.ZERO, true, true, CacheKeyPrefix.simple(), RedisSerializationContext.SerializationPair.fromSerializer(keySerializer), RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer),conversionService);
            }
        }

        assert redisCacheConfiguration != null;
        //通过RedisCacheManagerBuilder来创建RedisCacheManager，也可以直接new
        return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory).cacheDefaults(redisCacheConfiguration).build();
    }

    @Bean
    public RedisCacheManager employeeCacheManager(RedisConnectionFactory connectionFactory) throws InvocationTargetException, IllegalAccessException, InstantiationException {
        //对 对象类型（employee）和string类型的序列化
        Jackson2JsonRedisSerializer<Employee> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Employee.class);
        Jackson2JsonRedisSerializer<String> keySerializer = new Jackson2JsonRedisSerializer<>(String.class);

        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
        RedisCacheConfiguration.registerDefaultConverters(conversionService);
        RedisCacheConfiguration redisCacheConfiguration = null;

        Constructor[] constructors = RedisCacheConfiguration.class.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            constructor.setAccessible(true);
            if(constructor.getParameterTypes().length==7){//因为只有构造方法，所以判断方式比较随意
                redisCacheConfiguration = (RedisCacheConfiguration) constructor.newInstance(Duration.ZERO, true, true, CacheKeyPrefix.simple(), RedisSerializationContext.SerializationPair.fromSerializer(keySerializer), RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer),conversionService);
            }
        }

        assert redisCacheConfiguration != null;
        //通过RedisCacheManagerBuilder来创建RedisCacheManager，也可以直接new
        return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory).cacheDefaults(redisCacheConfiguration).build();
    }


    @Bean
    public RedisCacheManager deptCacheManager(RedisConnectionFactory connectionFactory) throws InvocationTargetException, IllegalAccessException, InstantiationException {
        //对 对象类型（employee）和string类型的序列化
        Jackson2JsonRedisSerializer<Department> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Department.class);
        Jackson2JsonRedisSerializer<String> keySerializer = new Jackson2JsonRedisSerializer<>(String.class);

        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
        RedisCacheConfiguration.registerDefaultConverters(conversionService);
        RedisCacheConfiguration redisCacheConfiguration = null;

        Constructor[] constructors = RedisCacheConfiguration.class.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            constructor.setAccessible(true);
            if(constructor.getParameterTypes().length==7){//因为只有构造方法，所以判断方式比较随意
                redisCacheConfiguration = (RedisCacheConfiguration) constructor.newInstance(Duration.ZERO, true, true, CacheKeyPrefix.simple(), RedisSerializationContext.SerializationPair.fromSerializer(keySerializer), RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer),conversionService);
            }
        }

        assert redisCacheConfiguration != null;
        //通过RedisCacheManagerBuilder来创建RedisCacheManager，也可以直接new
        return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory).cacheDefaults(redisCacheConfiguration).build();
    }




    //CacheManagerCustomizers可以来定制缓存的一些规则
//    @Primary  //将某个缓存管理器作为默认的， 注意实际开发中还是使用 RedisTemplate<Object, Object>
//    @Bean
//    public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate){
//        RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//        //key多了一个前缀
//
//        //使用前缀，默认会将CacheName作为key的前缀
//        cacheManager.setUsePrefix(true);
//
//        return cacheManager;
//    }

//    @Bean
//    public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate){
//        RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//        //key多了一个前缀
//
//        //使用前缀，默认会将CacheName作为key的前缀
//        cacheManager.setUsePrefix(true);
//
//        return cacheManager;
//    }


}
